home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / dev / misc / AmigaSDLsrc.lha / amisrc / SDL_cgxgl.c < prev    next >
C/C++ Source or Header  |  2000-08-11  |  10KB  |  390 lines

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     slouken@devolution.com
  21. */
  22.  
  23. #ifdef SAVE_RCSID
  24. static char rcsid =
  25.  "@(#) $Id: SDL_x11gl.c,v 1.1.2.20 2000/07/27 04:37:51 hercules Exp $";
  26. #endif
  27.  
  28. // #include <stdlib.h>    /* For getenv() prototype */
  29. // #include <string.h>
  30.  
  31. #include "SDL_events_c.h"
  32. #include "SDL_error.h"
  33. #include "SDL_cgxvideo.h"
  34. #include "SDL_cgxgl_c.h"
  35.  
  36. #define DEFAULT_OPENGL    "libGL.so.1"
  37.  
  38. /* return the preferred visual to use for openGL graphics */
  39. void *CGX_GL_GetVisual(_THIS)
  40. {
  41. #ifdef HAVE_OPENGL
  42.     /* 64 seems nice. */
  43.     int attribs[64];
  44.     int i;
  45.  
  46.     /* load the gl driver from a default path */
  47.     if ( ! this->gl_config.driver_loaded ) {
  48.             /* no driver has been loaded, use default (ourselves) */
  49.             if ( X11_GL_LoadLibrary(this, NULL) < 0 ) {
  50.                 return NULL;
  51.         }
  52.     }
  53.  
  54.     /* See if we already have a window which we must use */
  55.     if ( SDL_windowid ) {
  56.         XWindowAttributes a;
  57.         XVisualInfo vi_in;
  58.         int out_count;
  59.  
  60.         XGetWindowAttributes(SDL_Display, SDL_Window, &a);
  61.         vi_in.screen = SDL_Screen;
  62.         vi_in.visualid = XVisualIDFromVisual(a.visual);
  63.         glx_visualinfo = XGetVisualInfo(SDL_Display,
  64.                          VisualScreenMask|VisualIDMask, &vi_in, &out_count);
  65.         return glx_visualinfo;
  66.     }
  67.  
  68.         /* Setup our GLX attributes according to the gl_config. */
  69.         i = 0;
  70.         attribs[i++] = GLX_RGBA;
  71.     attribs[i++] = GLX_RED_SIZE;
  72.     attribs[i++] = this->gl_config.red_size;
  73.     attribs[i++] = GLX_GREEN_SIZE;
  74.     attribs[i++] = this->gl_config.green_size;
  75.     attribs[i++] = GLX_BLUE_SIZE;
  76.     attribs[i++] = this->gl_config.blue_size;
  77.  
  78.     if( this->gl_config.alpha_size ) {
  79.         attribs[i++] = GLX_ALPHA_SIZE;
  80.         attribs[i++] = this->gl_config.alpha_size;
  81.     }
  82.  
  83.     if( this->gl_config.buffer_size ) {
  84.                 attribs[i++] = GLX_BUFFER_SIZE;
  85.             attribs[i++] = this->gl_config.buffer_size;
  86.     }
  87.  
  88.     if( this->gl_config.double_buffer ) {
  89.         attribs[i++] = GLX_DOUBLEBUFFER;
  90.     }
  91.  
  92.     attribs[i++] = GLX_DEPTH_SIZE;
  93.     attribs[i++] = this->gl_config.depth_size;
  94.  
  95.     if( this->gl_config.stencil_size ) {
  96.         attribs[i++] = GLX_STENCIL_SIZE;
  97.         attribs[i++] = this->gl_config.stencil_size;
  98.     }
  99.  
  100.     if( this->gl_config.accum_red_size ) {
  101.             attribs[i++] = GLX_ACCUM_RED_SIZE;
  102.         attribs[i++] = this->gl_config.accum_red_size;
  103.     }
  104.  
  105.     if( this->gl_config.accum_green_size ) {
  106.             attribs[i++] = GLX_ACCUM_GREEN_SIZE;
  107.         attribs[i++] = this->gl_config.accum_green_size;
  108.     }
  109.  
  110.     if( this->gl_config.accum_blue_size ) {
  111.             attribs[i++] = GLX_ACCUM_BLUE_SIZE;
  112.         attribs[i++] = this->gl_config.accum_blue_size;
  113.     }
  114.  
  115.     if( this->gl_config.accum_alpha_size ) {
  116.             attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
  117.         attribs[i++] = this->gl_config.accum_alpha_size;
  118.     }
  119.  
  120.     attribs[i++] = None;
  121.  
  122.      glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display, 
  123.                           SDL_Screen, attribs);
  124.     if( !glx_visualinfo ) {
  125.         SDL_SetError( "Couldn't find matching GLX visual");
  126.         return NULL;
  127.     }
  128.     return glx_visualinfo;
  129. #else
  130.     SDL_SetError("CGX driver is not yet supporting OpenGL");
  131.     return NULL;
  132. #endif
  133. }
  134.  
  135. int CGX_GL_CreateWindow(_THIS, int w, int h)
  136. {
  137.     int retval;
  138. #ifdef HAVE_OPENGL
  139.     XSetWindowAttributes attributes;
  140.     unsigned long mask;
  141.     unsigned long black;
  142.  
  143.     black = (glx_visualinfo->visual == DefaultVisual(SDL_Display,
  144.                              SDL_Screen))
  145.                ? BlackPixel(SDL_Display, SDL_Screen) : 0;
  146.     attributes.background_pixel = black;
  147.     attributes.border_pixel = black;
  148.     attributes.colormap = SDL_XColorMap;
  149.     mask = CWBackPixel | CWBorderPixel | CWColormap;
  150.  
  151.     SDL_Window = XCreateWindow(SDL_Display, WMwindow,
  152.             0, 0, w, h, 0, glx_visualinfo->depth,
  153.             InputOutput, glx_visualinfo->visual,
  154.             mask, &attributes);
  155.     if ( !SDL_Window ) {
  156.         SDL_SetError("Could not create window");
  157.         return -1;
  158.     }
  159.     retval = 0;
  160. #else
  161.     SDL_SetError("CGX driver is not yet supporting OpenGL");
  162.     retval = -1;
  163. #endif
  164.     return(retval);
  165. }
  166.  
  167. int CGX_GL_CreateContext(_THIS)
  168. {
  169.     int retval;
  170. #ifdef HAVE_OPENGL
  171.     /* We do this to create a clean separation between X and GLX errors. */
  172.     XSync( SDL_Display, False );
  173.     glx_context = this->gl_data->glXCreateContext(GFX_Display, 
  174.                      glx_visualinfo, NULL, True);
  175.     XSync( GFX_Display, False );
  176.  
  177.     if (glx_context == NULL) {
  178.         SDL_SetError("Could not create GL context");
  179.         return -1;
  180.     }
  181.  
  182.     gl_active = 1;
  183. #else
  184.     SDL_SetError("CGX driver is not yet supporting OpenGL");
  185. #endif
  186.     if ( gl_active ) {
  187.         retval = 0;
  188.     } else {
  189.         retval = -1;
  190.     }
  191.     return(retval);
  192. }
  193.  
  194. void CGX_GL_Shutdown(_THIS)
  195. {
  196. #ifdef HAVE_OPENGL
  197.     /* Clean up OpenGL */
  198.     if( glx_context ) {
  199.         this->gl_data->glXMakeCurrent(GFX_Display, None, NULL);
  200.  
  201.         if (glx_context != NULL)
  202.             this->gl_data->glXDestroyContext(GFX_Display, glx_context);
  203.  
  204.         if( this->gl_data->glXReleaseBuffersMESA ) {
  205.             this->gl_data->glXReleaseBuffersMESA(GFX_Display,SDL_Window);
  206.         }
  207.         glx_context = NULL;
  208.     }
  209.     gl_active = 0;
  210. #endif /* HAVE_OPENGL */
  211. }
  212.  
  213. #ifdef HAVE_OPENGL
  214.  
  215. /* Make the current context active */
  216. int CGX_GL_MakeCurrent(_THIS)
  217. {
  218.     int retval;
  219.  
  220.     retval = 0;
  221.     if ( ! this->gl_data->glXMakeCurrent(GFX_Display,
  222.                                          SDL_Window, glx_context) ) {
  223.         SDL_SetError("Unable to make GL context current");
  224.         retval = -1;
  225.     }
  226.     XSync( GFX_Display, False );
  227.  
  228.     /* More Voodoo X server workarounds... Grr... */
  229.     SDL_Lock_EventThread();
  230.     X11_CheckDGAMouse(this);
  231.     SDL_Unlock_EventThread();
  232.  
  233.     return(retval);
  234. }
  235.  
  236. /* Get attribute data from glX. */
  237. int CGX_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
  238. {
  239.     int retval;
  240.     int glx_attrib = None;
  241.  
  242.     switch( attrib ) {
  243.         case SDL_GL_RED_SIZE:
  244.         glx_attrib = GLX_RED_SIZE;
  245.         break;
  246.         case SDL_GL_GREEN_SIZE:
  247.         glx_attrib = GLX_GREEN_SIZE;
  248.         break;
  249.         case SDL_GL_BLUE_SIZE:
  250.         glx_attrib = GLX_BLUE_SIZE;
  251.         break;
  252.         case SDL_GL_ALPHA_SIZE:
  253.         glx_attrib = GLX_ALPHA_SIZE;
  254.         break;
  255.         case SDL_GL_DOUBLEBUFFER:
  256.         glx_attrib = GLX_DOUBLEBUFFER;
  257.         break;
  258.         case SDL_GL_BUFFER_SIZE:
  259.         glx_attrib = GLX_BUFFER_SIZE;
  260.         break;
  261.         case SDL_GL_DEPTH_SIZE:
  262.         glx_attrib = GLX_DEPTH_SIZE;
  263.         break;
  264.         case SDL_GL_STENCIL_SIZE:
  265.         glx_attrib = GLX_STENCIL_SIZE;
  266.         break;
  267.         case SDL_GL_ACCUM_RED_SIZE:
  268.         glx_attrib = GLX_ACCUM_RED_SIZE;
  269.         break;
  270.         case SDL_GL_ACCUM_GREEN_SIZE:
  271.         glx_attrib = GLX_ACCUM_GREEN_SIZE;
  272.         break;
  273.         case SDL_GL_ACCUM_BLUE_SIZE:
  274.         glx_attrib = GLX_ACCUM_BLUE_SIZE;
  275.         break;
  276.         case SDL_GL_ACCUM_ALPHA_SIZE:
  277.         glx_attrib = GLX_ACCUM_ALPHA_SIZE;
  278.         break;
  279.         default:
  280.         return(-1);
  281.     }
  282.  
  283.     retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value);
  284.  
  285.     return retval;
  286. }
  287.  
  288. void CGX_GL_SwapBuffers(_THIS)
  289. {
  290.     this->gl_data->glXSwapBuffers(GFX_Display, SDL_Window);
  291. }
  292.  
  293. #endif /* HAVE_OPENGL */
  294.  
  295. void CGX_GL_UnloadLibrary(_THIS)
  296. {
  297. #ifdef HAVE_OPENGL
  298.     if ( this->gl_config.driver_loaded ) {
  299.         dlclose(this->gl_config.dll_handle);
  300.  
  301.         this->gl_data->glXChooseVisual = NULL;
  302.         this->gl_data->glXCreateContext = NULL;
  303.         this->gl_data->glXDestroyContext = NULL;
  304.         this->gl_data->glXMakeCurrent = NULL;
  305.         this->gl_data->glXSwapBuffers = NULL;
  306.  
  307.         this->gl_config.dll_handle = NULL;
  308.         this->gl_config.driver_loaded = 0;
  309.     }
  310. #endif
  311. }
  312.  
  313. #ifdef HAVE_OPENGL
  314.  
  315. /* Passing a NULL path means load pointers from the application */
  316. int CGX_GL_LoadLibrary(_THIS, const char* path) 
  317. {
  318.     void* handle;
  319.     int dlopen_flags;
  320.  
  321.      if ( gl_active ) {
  322.          SDL_SetError("OpenGL context already created");
  323.          return -1;
  324.      }
  325.  
  326. #ifdef RTLD_GLOBAL
  327.     dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
  328. #else
  329.     dlopen_flags = RTLD_LAZY;
  330. #endif
  331.     handle = dlopen(path, dlopen_flags);
  332.     /* Catch the case where the application isn't linked with GL */
  333.     if ( (dlsym(handle, "glXChooseVisual") == NULL) && (path == NULL) ) {
  334.         dlclose(handle);
  335.         path = getenv("SDL_VIDEO_GL_DRIVER");
  336.         if ( path == NULL ) {
  337.             path = DEFAULT_OPENGL;
  338.         }
  339.         handle = dlopen(path, dlopen_flags);
  340.     }
  341.     if ( handle == NULL ) {
  342.         SDL_SetError("Could not load OpenGL library");
  343.         return -1;
  344.     }
  345.  
  346.     /* Unload the old driver and reset the pointers */
  347.     X11_GL_UnloadLibrary(this);
  348.  
  349.     /* Load new function pointers */
  350.     this->gl_data->glXChooseVisual = dlsym(handle, "glXChooseVisual");
  351.     this->gl_data->glXCreateContext = dlsym(handle, "glXCreateContext");
  352.     this->gl_data->glXDestroyContext = dlsym(handle, "glXDestroyContext");
  353.     this->gl_data->glXMakeCurrent = dlsym(handle, "glXMakeCurrent");
  354.     this->gl_data->glXSwapBuffers = dlsym(handle, "glXSwapBuffers");
  355.     this->gl_data->glXGetConfig = dlsym(handle, "glXGetConfig");
  356.     /* We don't compare below for this in case we're not using Mesa. */
  357.     this->gl_data->glXReleaseBuffersMESA = dlsym( handle, "glXReleaseBuffersMESA" );
  358.  
  359.     if ( (this->gl_data->glXChooseVisual == NULL) || 
  360.          (this->gl_data->glXCreateContext == NULL) ||
  361.          (this->gl_data->glXDestroyContext == NULL) ||
  362.          (this->gl_data->glXMakeCurrent == NULL) ||
  363.          (this->gl_data->glXSwapBuffers == NULL) ||
  364.          (this->gl_data->glXGetConfig == NULL) ) {
  365.         SDL_SetError("Could not retrieve OpenGL functions");
  366.         return -1;
  367.     }
  368.  
  369.     this->gl_config.dll_handle = handle;
  370.     this->gl_config.driver_loaded = 1;
  371.     if ( path ) {
  372.         strncpy(this->gl_config.driver_path, path,
  373.             sizeof(this->gl_config.driver_path)-1);
  374.     } else {
  375.         strcpy(this->gl_config.driver_path, "");
  376.     }
  377.     return 0;
  378. }
  379.  
  380. void *CGX_GL_GetProcAddress(_THIS, const char* proc)
  381. {
  382.     void* handle;
  383.     
  384.     handle = this->gl_config.dll_handle;
  385.  
  386.     return dlsym(handle, proc);
  387. }
  388.  
  389. #endif /* HAVE_OPENGL */
  390.